//Eli Elder
//play entire game test

#include "dominion.h"
#include "dominion_helpers.h"
#include "interface.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h> 
#include <assert.h>
#include <math.h>
#include "rngs.h"
#include <time.h>

void printOut(FILE *gameResults, struct gameState *game){
    int i;
    char cardName[30];
    //taken from the printstate
    int actions = game->numActions;
    int coins = game->coins;
    int numBuys= game->numBuys;
    int currentPlayer = game->whoseTurn;
    int phase = game->phase; 
    char phaseName[MAX_STRING_LENGTH];
    phaseNumToName(phase, phaseName);

	//print that print out stuff
    fprintf(gameResults, "Player: %d\n%s phase\n%dactions\n%d coins\n%d buys\n\n", currentPlayer, phaseName, actions, coins, numBuys);

    //also keep track of the cards, could use every turn as well
     for(i = 0; i < treasure_map; i++){
	cardNumToName(i, cardName);
	fprintf(gameResults, "%s has %d\n", cardName, game->supplyCount[i]);
    }
}

int main(int argc, char *argv[]){
    //used in initialization
    int players;
    int kingCards[10];
    int cardFound;
    int kingCard; 
    //used for loops
    int i;
    int j;
    int isKingCard; 
    int try;
    int breakOut; 
    //used for the random seed (haha)
    int randomSeed;
    //used for the return value from the functions called
    int returnVal;
    //these are used for prints and for 
    int turn;
    //used for card prints and card choice selection events
    int cardPosition;
    int card;
    int choice1;
    int choice2;
    int choice3;
    int cardLocation;
    int numSameCard;
    //used for the buy 
    int randomBuy;
    //the game state
    struct gameState gState;
    //used to print out the card name
    char cardName[30];
    //used to get the winners and such
    int playerArray[4];
    //used?
    int bonus;
    //make file
    FILE *gameResults;


    //open it to write and overwrite it
    gameResults = fopen("gameResults.out","w+");
    //setup our random number 
    srand(time(NULL));
    
    //setup the random seed part
    randomSeed = atoi(argv[1]);

    //taken from the player.c code to setup the random seed, cause I don't really know what it is
    if(argc != 2){
	printf("Usage: player [integer random number seed]\n");
	fclose(gameResults);
	return EXIT_SUCCESS;
    }

    if(randomSeed <= 0){
	printf("Usage: player [integer random number seed]\n");
	fclose(gameResults);
	return EXIT_SUCCESS;
    }	
    
    //setup the gamestate as blank
    memset(&gState, 0, sizeof(struct gameState));
    
    //get the random number of players  (always need 2)
    players = floor(rand() % 4) + 2;
    	
    i = 0;
    //get the 10 random kingdom cards, else I would use names 
    while(i < 10){
	//start off saying we don't have it
	cardFound = 0;
	//kingdom cards are from 7 to 26 else I would use the car names
	kingCard = floor(rand() % 20) + 7;
	
	//loop through to see if we have it already
	for(j = 0; j <= i; j++){
	    //if we have the card say so
	    if(kingCard == kingCards[j]){
		cardFound = 1;
	    }
	}
	    
	//if we havent found the card set it for our game
	if(cardFound == 0){
	    kingCards[i] = kingCard;
	    cardFound = 0;
	    //also go to next spot
	    i++;
	}
    }
    

    //print out the initial starting points, players, cards
    fprintf(gameResults, "GAME STARTING\n");
    fprintf(gameResults, "Number of players %d\n", players);
    fprintf(gameResults,  "Kingdom Cards\n");
    for(i = 0; i < 10; i++){
	cardNumToName(kingCards[i], cardName);
	fprintf(gameResults,  "Card %d: %s\n", i, cardName);
    }
    //initialize the game
    returnVal = initializeGame(players, kingCards, randomSeed, &gState);
    if(returnVal != 0){
	printf("Initialize game failed, returning because a broken game is bad\n");
	fclose(gameResults);
	return 0;
    }
	
	//print out the games initialized and our print out item
    fprintf(gameResults,  "Game Initialized!!!!!!!!!!!!!!!!!!!!!!\n\n");
    printOut(gameResults, &gState);

    turn = 0;
    //keep the game going until it ends,
    while(isGameOver(&gState) == 0){
	//tell us how the game is going now/whose (might have to be turn % players)
	fprintf(gameResults,  "Player %d starting their turn %d\n", whoseTurn(&gState), turn / players);
	
	//initialize try to 0
	try = 0;
	while(gState.numActions > 0 && try < gState.handCount[whoseTurn(&gState)] * 2){
		//initialize cardPoisition to 0 an dincrement the try's
	    cardPosition = 0;
	    try++;
	    //do actions, make sure we can and try to print if we cant (have to do the set up for each card that needs it
	    //go through twice because I am randomizing which card to play and we might get the same a couple times
	    //but only twice so we don't go FOREVER!
	    for(i = 0; i < gState.handCount[whoseTurn(&gState)] * 2; i++){
		//get a random card from the players hand
		cardPosition = floor(rand() % gState.handCount[whoseTurn(&gState)]);
		card = gState.hand[whoseTurn(&gState)][cardPosition];

		//the card must be a kingdom card not trasure or other thing
		if(card >= adventurer && card <= treasure_map){
		    cardNumToName(card, cardName);
		    fprintf(gameResults, "Player %d, is trying to play card %s\n", whoseTurn(&gState), cardName);
		
		    //setup the choice/bonus as -1 so we don't accidentally pick curse which == 0
		    choice1 = -1;
		    choice2 = -1;
		    choice3 = -1;
		    bonus = -1;
		    breakOut = 0;
		    //now setup the items for the kingdom cards that need it
		    if(card == adventurer){
			//dont need anything
			isKingCard = 1;
		    }else if (card == council_room){
			//dont need anything	
			isKingCard = 1;
		    }else if (card == feast){
			while(breakOut == 0){
			    //loop forever unti lwe find a good card
			    choice1 = floor(rand() % treasure_map);
			    //if the cost is less or equal to 5 we break 
			    if(getCost(choice1) <= 5){
				breakOut = 1;
			    }
			    //else we should conitnue until it does
			}
			//print out what card we are gaiing
			cardNumToName(choice1, cardName);
			fprintf(gameResults,  "Using feast we now gain %s\n", cardName);
			isKingCard = 1;
		    }else if (card == gardens){
			//its boroken so nothing
			isKingCard = 1;
		    }else if (card == mine){
			while(breakOut == 0){
			    //loop forever until we find a good card
			    //get the card location and the card at that location
			    cardLocation = floor(rand() % gState.handCount[whoseTurn(&gState)]);
			    choice1 = gState.hand[whoseTurn(&gState)][cardLocation];
			    
			    if(choice1 == copper){
				//if the card is copper get silver
				choice2 = silver;
				breakOut = 1;
				}else if(choice1 == silver){
				//if the card is silver get gold
				choice2 = gold;
				breakOut = 1;
			    }else if(choice1 == gold){
				//if the card is gold this was dumb but whatever
				choice2 = gold;
				breakOut = 1 ;
			    }
			    //else we should conitnue until it does
			}
			//print out which given and which gained
			cardNumToName(choice1, cardName);
			fprintf(gameResults,  "Using mine we dropped %s and gained ", cardName);
			cardNumToName(choice2, cardName);
			fprintf(gameResults,  "%s\n", cardName);
			isKingCard = 1;
		    }else if (card == remodel){
			while(breakOut == 0){
			    //loop forever unti lwe find a good card
				//get the card location and the card at that location
			    cardLocation = floor(rand() % gState.handCount[whoseTurn(&gState)]);
			    choice1 = gState.hand[whoseTurn(&gState)][cardLocation];
			    //get the card to gain
			    choice2 = floor(rand() % treasure_map);
			    //if the cost is less or equal to 5 we break 
			    if(getCost(choice1) + 2 <= getCost(choice2)){
				fprintf(gameResults, "gogo\n");
				breakOut = 1;
			    }
			    //else we should conitnue until it does
			}
			//print out which given and which gained
			cardNumToName(choice1, cardName);
			fprintf(gameResults,  "Using remodel we dropped %s and gained ", cardName);
			cardNumToName(choice2, cardName);
			fprintf(gameResults,  "%s\n", cardName);
			isKingCard = 1;
		    }else if (card == smithy){
			//dont need anything
			isKingCard = 1;
		    }else if (card == village){
			//dont need anything
			isKingCard = 1;
		    }else if (card == baron){
			//randomize if we want to discard the estate the card does the lookup
			choice1 = floor(rand() % 2);
			isKingCard = 1;
		    }else if (card == great_hall){
			//dont need anything
			isKingCard = 1;
		    }else if (card == minion){
			//randomize if we want to do the first option
			choice1 = floor(rand() % 2);
			//randomize if we want to do the 2nd option (this seems wrong)
			choice2 = floor(rand() % 2);
			
			//print out if we took certain choices
			fprintf(gameResults,  "Using minion choice1 was: %d and choice2 was: %d\n", choice1, choice2);
			isKingCard = 1;
		    }else if (card == steward){
			//if we want choice 1 or 2 or 3
			choice1 = floor(rand() % 3);
			
			//when its not 1 or 2 for choice 1 do choice 3 which discards cards
			if(choice1 != 1 && choice1 != 2){
			    //have to keep looping so we can make sure we don't discard the steward
			    while(breakOut == 0){
				//randomly pick those 2 cards
				choice2 = floor(rand() % gState.handCount[whoseTurn(&gState)]);
				choice3 = floor(rand() % gState.handCount[whoseTurn(&gState)]);
				//if we have 3 or more cards in our hand
				if(gState.handCount[whoseTurn(&gState)] >= 3){
				    //make sure 3 and 2 arent the same
				    while(choice2 == choice3){
					//change 3
					choice3 = floor(rand() % gState.handCount[whoseTurn(&gState)]);
				    }
				}
				//only break if card2 and card3 are not the steward, else do it again! weee!
				if(choice2 != cardPosition && choice3 != cardPosition){
				    breakOut = 1;
				}
			    }
				
			}
			
			//print out which given and which gained
			fprintf(gameResults,  "Using steward choice1 was: %d\n", choice1);
			    if(choice2 >= 0){
				cardNumToName(choice2, cardName);
				fprintf(gameResults,  "Steward gained card %s\n", cardName);
			    }
			    if(choice3 >= 0){
				cardNumToName(choice3, cardName);
				fprintf(gameResults,  "Steward gained card %s\n", cardName);
			    }
			isKingCard = 1;
		    }else if (card == tribute){
			//dont need anything
			isKingCard = 1;
		    }else if (card == ambassador){
			    //get the card to discard
			choice1 = floor(rand() % gState.handCount[whoseTurn(&gState)]);
			
			while(breakOut == 0){
			    //randomize the amount of cards to get rid of
			    choice2 = floor(rand() % 2);
			    
			    //need ot make sure we have that many cards
			    for(i = 0; i < gState.handCount[whoseTurn(&gState)]; i++){
				//we don't want to count the card we are discarding already
				if(i != choice1){
				    //see if the card is the same as choice1 to discard
				    if(gState.hand[whoseTurn(&gState)][i] == gState.hand[whoseTurn(&gState)][choice1]){
					numSameCard++;
				    }
				}
			    }
			    
			    //make sure choice2 cards given away is less than the count of the same cards
			    if(choice2 < numSameCard){
				//make sure the number of players is less than the amount left including the discards else try again
				if(gState.numPlayers < supplyCount(choice1, &gState) + numSameCard){
				    breakOut = 1;
				}
			    }							
			}
			
			//print out which given and which gained
			cardNumToName(choice1, cardName);
			fprintf(gameResults,  "Ambassador dropped/gained card %s\n", cardName);
			cardNumToName(choice2, cardName);
			fprintf(gameResults,  "Amount of cards dropped were %d\n", choice2);
			isKingCard = 1;
		    }else if (card == cutpurse){
			//dont need anything
			isKingCard = 1;
		    }else if (card == embargo){
			while(breakOut == 0){
			    //randomize the card to put the embargo token on
			    choice1 = floor(rand() % treasure_map);
			    //have to make sure there are some of those cards
			    if(supplyCount(choice1, &gState) > 0){
				breakOut = 1;
			    }
			}
			
			//print out which card got the embargo
			cardNumToName(choice1, cardName);
			fprintf(gameResults,  "Embargo token on card %s\n", cardName);
			isKingCard = 1;
		    }else if (card == outpost){
			//dont need anything
			isKingCard = 1;
		    }else if (card == salvager){
			//get the card
			choice1 = floor(rand() % gState.handCount[whoseTurn(&gState)]);
			//print out what the salvager got
			cardNumToName(choice1, cardName);
			fprintf(gameResults,  "Salvaged card %s\n", cardName);
			isKingCard = 1;
		    }else if (card == sea_hag){
			//dont need anything
			isKingCard = 1;
		    }else if (card == treasure_map){
			//dont need anything
			isKingCard = 1;
		    }
		}else{
			//set the card 
		    isKingCard = 0;
		}
		
		if(isKingCard == 1){
		    break;
		}
	    }
	    
	    if(isKingCard == 1){
		//now I can play the card
		returnVal = playCard(cardPosition ,choice1, choice2, choice3, &gState);
		if(returnVal != 0){
			//if the card fails 
		    cardNumToName(handCard(cardPosition, &gState), cardName);
		    printf("The card %s failed\n", cardName);
		    //fclose(gameResults);
		    //return 0; 
		}else{
			//when the card is played 
		    cardNumToName(handCard(cardPosition, &gState), cardName);
		    fprintf(gameResults, "%d played card %s\n ", whoseTurn(&gState), cardName);
		    break;
		}		  
	    } else {
			//this is if the isKingCard is 0 meaning the card isnt a king card 
	    }
	}
	//print sometext
	fprintf(gameResults,  "Actions over, starting buys\n\n");
	//reset the try variable
	try = 0;
	while(gState.numBuys > 0 && try < treasure_map){
	    //try to buy cards, have to make sure it exists and is a card we can buy
	    
	    //get a random card to buy
	    randomBuy = floor(rand() % treasure_map);
	    //make sure it exists/has supply
	    if(supplyCount(randomBuy, &gState) < 1){
		//we dont have that card, tell them
		cardNumToName(randomBuy, cardName);
		fprintf(gameResults,  "The card: %s does not have any left, or doesn't exist\n", cardName);
	    }else{
		//we have the card check which we should buy
		returnVal =  buyCard(randomBuy, &gState);
		if(returnVal != 0){
		    cardNumToName(randomBuy, cardName);
		    printf("Trying to buy the card: %s failed, it cost %d, you have %d coins\n", cardName, getCost(randomBuy), gState.coins);
		} else {
		    cardNumToName(randomBuy, cardName);
		    fprintf(gameResults, "Trying to buy the card: %s was great success\n", cardName);
		}
	    }
	    try++;
	}

	//end the players turn and increase the turn count
	returnVal = endTurn(&gState);
	if(returnVal != 0){
	    printf("End turn failed\n");
	    fclose(gameResults);
	    return 0;
	}
	
	//print a break for the end of this turn, migh tneed turn % players
	fprintf(gameResults,  "End of player: %d turn number %d\n\n", whoseTurn(&gState), turn / players);
	turn++;
	//printf("turn %d\n", turn); 
    }
 
    printOut(gameResults, &gState);

    //print the game over thing
    fprintf(gameResults,  ("The game is now over\n\n"));
    
    //show who won get winnders
    getWinners(playerArray, &gState);
    //say we are done 
    for(i = 0; i < players; i++){
	fprintf(gameResults,  "Player number: %d had %d points\n", i, scoreFor(i, &gState));
	if(playerArray[i] == 1 ){
	    fprintf(gameResults,  "Player number: %d is a winner!!!!!!!!!\n\n", i);
	}
    }
    fprintf(gameResults, "\nThank you, please test again\n");
    //close the file as we exit
    fclose(gameResults);
    return 0;
}

